﻿namespace _09_Tetris
{
    internal class Game
    {
        bool isOver;
        long lastTime, currentTime, fixedTime;
        int speed, fps;
        Shape shape;
        Shape nextShape;
        Shape hintShape;
        Map map;
        Random rand;
        int[] array;
        int index;
        int currentType, nextType;
        Input input;
        Information information;

        public Game()
        {
            Console.CursorVisible = false;
            isOver = false;
            speed = 6;
            fps = 30;
            map = new Map();
            rand = new Random();
            array = new int[7];
            index = 7;
            nextType = GetNextType();
            input = new Input();
            information = new Information(30,2,50,input);
            for (int i = 0; i < 7; i++)
            {
                information.AddInfo("hello", (ConsoleColor)i);
            }
        }
        public void Play()
        {
            Init();
            lastTime = DateTime.Now.Ticks;
            fixedTime = DateTime.Now.Ticks;
            while (!isOver)
            {
                input.Update();
                Input();
                Update();
                currentTime = DateTime.Now.Ticks;
                if ( currentTime - fixedTime > 1000_0000 / speed )
                {
                    FixedUpdate();
                    fixedTime = DateTime.Now.Ticks;
                }
                if ( currentTime - lastTime > 1000_0000 / fps )
                {
                    Render();
                    lastTime = DateTime.Now.Ticks;
                }
            }
            End();
        }

        void Init()
        {
            map.Init();
            SpawnShape();
        }
        void Input()
        {
            if (input.IsKeyPressed(ConsoleKey.W))
            {
                //顺时针转
                shape.Rotate(true);
                hintShape.Clear();
            }
            if (input.IsKeyPressed(ConsoleKey.S))
            {
                //加速下落
            }
            if (input.IsKeyPressed(ConsoleKey.A))
            {
                //向左移动
                if (!shape.CheckHit(Map.Type.Wall, -1, 0))
                {
                    shape.Move(-1);
                    hintShape.Clear();
                }
            }
            if (input.IsKeyPressed(ConsoleKey.D))
            {
                //向右移动
                if (!shape.CheckHit(Map.Type.Wall, 1, 0))
                {
                    shape.Move(1);
                    hintShape.Clear();
                }
            }
            if (input.IsKeyPressed(ConsoleKey.Z))
            {
                //逆时针转da
                shape.Rotate(false);
                hintShape.Clear();
            }
            if (input.IsKeyPressed(ConsoleKey.Spacebar))
            {
                //直接下落
                shape.DropBottom();
            }
            information.Input();
        }
        void Update()
        {
            shape.Update();
            hintShape.SetPos(shape.GetPosX(), 1);
            hintShape.SetDir(shape.GetDir());
            hintShape.DropBottom();
            information.Update();
        }
        void FixedUpdate()
        {
            if (!shape.CheckHit(Map.Type.Wall, 0, 1))
            {
                shape.Drop();
            }
            else
            {
                // 触底
                // 固化
                shape.Solidify();
                // 检测是否有应该消除的行
                map.ClearLine();
                // 生成新的方块
                SpawnShape();
            }
        }
        void Render()
        {
            map.Render();
            nextShape.Render();

            hintShape.Render();
            shape.Render();
            information.PrintInfo();
        }
        void End()
        {

        }

        void SpawnShape()
        {
            currentType = nextType;
            nextType = GetNextType();

            switch (currentType)
            {
                case 0:
                    shape = new Shape_I(ref map);
                    hintShape = new Shape_I(ref map);
                    break;
                case 1:
                    shape = new Shape_J(ref map);
                    hintShape = new Shape_J(ref map);
                    break;
                case 2:
                    shape = new Shape_L(ref map);
                    hintShape = new Shape_L(ref map);
                    break;
                case 3:
                    shape = new Shape_O(ref map);
                    hintShape = new Shape_O(ref map);
                    break;
                case 4:
                    shape = new Shape_S(ref map);
                    hintShape = new Shape_S(ref map);
                    break;
                case 5:
                    shape = new Shape_T(ref map);
                    hintShape = new Shape_T(ref map);
                    break;
                case 6:
                    shape = new Shape_Z(ref map);
                    hintShape = new Shape_Z(ref map);
                    break;
            }

            switch (nextType)
            {
                case 0:
                    nextShape = new Shape_I(ref map);
                    break;
                case 1:
                    nextShape = new Shape_J(ref map);
                    break;
                case 2:
                    nextShape = new Shape_L(ref map);
                    break;
                case 3:
                    nextShape = new Shape_O(ref map);
                    break;
                case 4:
                    nextShape = new Shape_S(ref map);
                    break;
                case 5:
                    nextShape = new Shape_T(ref map);
                    break;
                case 6:
                    nextShape = new Shape_Z(ref map);
                    break;
            }

            hintShape.SaveColor();
            nextShape.SetPos(16, 4);
            isOver = shape.CheckHit(Map.Type.Wall, 0, 1);
        }

        // 如何随机生成方块
        // 如何让边框阻挡方块
        // 如何判断方块到底了 ->无法继续掉落
        // 如何让地图记录到底的方块
        // 如何消行 核心逻辑

        void ShuffleArray(int[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                int index = rand.Next(0, arr.Length);
                int temp = arr[i];
                arr[i] = arr[index];
                arr[index] = temp;
            }
        }

        int GetNextType()
        {
            if(index > array.Length - 1)
            {
                for(int i = 0;i < array.Length; i++)
                {
                    array[i] = i;
                }
                ShuffleArray(array);
                index = 0;
            }
            return array[index++];
        }
    }
}
